#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os, sys, base64
import subprocess as sp
import lxml.etree as etree
import logging as log
import gobject, gtk, appindicator

def menuitem_response(w, buf): print buf

class Conny:
	def __init__(self):
		log.basicConfig(level=log.INFO,format='%(asctime)s %(levelname)s %(message)s',
			filename=os.path.expanduser('.conny.log'))
		log.info("Here's Conny!")
				
		self.ind = appindicator.Indicator("Conny", "terminal-tango", 
			appindicator.CATEGORY_APPLICATION_STATUS)

		self.load_xml()
		self.menu = self.get_menu(self.hosts)
		
		self.ind.set_status(appindicator.STATUS_ACTIVE)
		self.ind.set_attention_icon("indicator-messages-new")
		self.ind.set_menu(self.menu)
		self.get_static_menu()
		
		gtk.main()
		
	def connect(self, menu, xpath):
		try:
			xpath = '//hosts/{}'.format(xpath)
			#log.info(type(self.xtree))
			log.info('connect: %s' % xpath)			
			#n = self.xtree.find("//host[@name='%s']" % menu.get_label())			
			n = self.xtree.find(xpath)
			#log.info(type(n))			
			user = n.get("user")
			host = n.get("host")
			port = n.get("port") 
			name = n.get("name")
			#' -p%s'%n.get("port") if n.get("port") is not None else ''			
			pswd = '' if n.get("password") is None else base64.b64decode(n.get("password"))
			if n.get("type") == "ssh":
				port = ' -p%s' % port if port is not None else ''
				args = "gnome-terminal --disable-factory --sm-client-disable -x ssh "
				#if port is not None: port = ' -p%s' % port
				if self.xtree.find("//host[@name='%s']" % n.get("proxy")) is not None: 
					pn = self.xtree.find("//host[@name='%s']" % n.get("proxy"))
					_user = pn.get("user")
					_host = pn.get("host")
					_port = ' -tp%s' % pn.get("port") if pn.get("port") is not None else ' -t'					
					args += "%(_user)s@%(_host)s%(_port)s ssh %(user)s@%(host)s" % locals()
				else: 
					args += "%(user)s@%(host)s%(port)s" % locals()
			elif n.get("type") == "rdp":
				pswd = base64.b64decode(n.get("password"))
				domain = ' -d %s' % n.get("domain") if n.get("domain") is not None else ''
				console = ' -0' if n.get('console') is not None else ''
				if port is not None: host = '%s:%s' % (host,port)
				if self.xtree.find("//host[@name='%s']" % n.get("proxy")) is not None: 
					pn = self.xtree.find("//host[@name='%s']" % n.get("proxy"))
					log.info(pn)
					#if sshtunnel(host):
						#host = 
				rdpdim = self.getSR()				
				args = 'rdesktop%(domain)s -u %(user)s -p %(pswd)s -g %(rdpdim)s -k da -a 16 -z -x l -T %(name)s%(console)s -r sound:off %(host)s' %  locals()
		except Exception as e: log.error('connect: %s' % e)
		else:
			run = sp.Popen(args.split(' '), stdin=sp.PIPE, stdout=sp.PIPE)
			log.info(args if pswd == '' else args.replace(pswd,'XXXXXXXX'))
			return run
			
	def sshtunnel(self,l,r,host):
		tnl = 'ssh -L 127.0.0.127:%(lport)s:%(raddr)s:%(rport)s '
		tunnel = sp.Popen(tnl.split(' '), stdin=sp.PIPE, stdout=sp.PIPE)
		#log.info(
		return tunnel

	def get_menu(self, node):
		menu = gtk.Menu()
		#log.info(sys._getframe().f_code.co_name)
		for l in node.iterchildren():
			if l.tag == "host": 
				m = gtk.MenuItem(l.get("name"))
				m.set_tooltip_text("%s@%s%s (%s)" % 
					(l.get("user"),l.get("host"),':'+l.get("port") if l.get("port") is not None else '',l.get("type")))
				m.connect('activate', self.connect, self.xtree.getpath(l)[12:])
				menu.append(m)
			elif l.tag == "menu": 
				sub = gtk.CheckMenuItem(l.get("name"))
				sub.connect("toggled", self.callback, "")
				sub.set_submenu(self.get_menu(l))
				menu.append(sub)
			
		menu.show_all()
		return menu

	def get_menu_test(self):
		menu = gtk.Menu()
		for i in range(3):
			item = gtk.CheckMenuItem("Testmenu %d" % i)
			# this is where you would connect your menu item up with a function:    
			#menus.connect("activate", self.menuitem_response, buf)
			#for n in range(4):
			#	z = "Test-undermenu - %d" % i
			#	subs = gtk.MenuItem(z)
			#	subs.connect("activate", self.menuitem_response, z)
			#	menus.append(subs)
			menu.append(item)
		return menu

	def menuitem_response(self, w, buf): print buf

	def getSR(self):
		try: 
			sr = sp.check_output(['xrandr'], shell=True)
			z = [ln.strip()[:ln.strip().find(' ')].split('x') for ln in sr.split('\n') if ln.find('*')!=-1]
			z = min([[str(int(w)-80),str(int(h)-50)] for (w,h) in z])
			log.info('getSR {}'.format(z))
			#z = [['1200','950']]
		except Exception as e: log.error(e)
		else:
			z = 'x'.join(z)
			return z
		
	def getvalue(self, node, param):
		return node.get(param) if node.get(param) is not None else ''
		
	def load_xml(self):
		#self.xmlfilename = os.path.expanduser('~/.config/conny/conny.xml')
		self.xmlfilename = os.path.expanduser('~/Ubuntu One/conny.xml')
		self.xtree = etree.parse(self.xmlfilename)
		self.hosts = self.xtree.getroot().find('hosts')
		self.hostsmenu = self.get_menu(self.hosts)

	def get_static_menu(self):
		self.menu.append(gtk.SeparatorMenuItem())
		sub = gtk.Menu()
		_restart = gtk.MenuItem(gtk.STOCK_REFRESH) #ImageMenuItem.new_from_stock(, None)
		_restart.connect("activate", self.restart)
		sub.append(_restart)
		#_restart = gtk.ImageMenuItem.new_from_stock(gtk.STOCK_REFRESH, None)
		#_restart.connect("activate", self.restart)
		#sub.append(_restart)

		_quit = gtk.MenuItem(gtk.STOCK_QUIT) #ImageMenuItem.new_from_stock(, None)
		_quit.connect("activate", self._quit)
		sub.append(_quit)
		
		subitem = gtk.CheckMenuItem("Conny...")
		subitem.connect("toggled", self.callback, "")
		subitem.set_submenu(sub)
		self.menu.append(subitem)
		self.menu.show_all()
		
		"""
		menu = gtk.CheckMenuItem('Hey')
		_restart = gtk.MenuItem('Rehfresh') #ImageMenuItem.new_from_stock(gtk.STOCK_REFRESH, None)
		_restart.connect("activate", self.restart)
		menu.append(_restart)
		_destroy = gtk.MenuItem('Quit') #ImageMenuItem.new_from_stock(gtk.STOCK_QUIT, None)
		_destroy.connect('activate', self.destroy)
		menu.append(_destroy)
		_about = gtk.MenuItem('About') #ImageMenuItem.new_from_stock(gtk.STOCK_ABOUT, None)
		_about.connect("activate", self.show_about)
		menu.append(_about)		
		return menu
		"""
		#_sep = Gtk.SeparatorMenuItem()
		#print _sep.get_style()
		#_sep.style.separator-height
		#menu.append(_sep)
		#_reload = Gtk.ImageMenuItem.new_from_stock(Gtk.STOCK_MEDIA_REWIND, None)
		#_reload.connect("activate", self.reload_menu)		
		#menu.append(_reload)	
		
	def rightclick(self, icon, button, time):		
		self.rightmenu.show_all()
		self.rightmenu.popup(None, None, self.pos(self.rightmenu), None, button, time)

	def callback(self, widget, data=None): widget.set_active(False)
	
	def _quit(self,whatever):
		sys.exit()
	
	def pos(self, menu):
		def fixfunc(a, b): return (self.icon.position_menu(menu, self.icon))
		return fixfunc 

	def show_about(self, widget):
		aboutDialog = Gtk.AboutDialog(version='0.9',license='GPL',
			program_name='Conny, the Connection Pusher',
			authors=['James Bond','Chuck Norris','Morten Abildgaard <morten@abildgaard.org>'])
		aboutDialog.run()
		aboutDialog.destroy()

	def restart(self,whatever):	
		try:
			log.info('Restarting')
			log.info('%s' % sys.argv[0])
			run = sp.Popen(['python',sys.argv[0]], stdin=sp.PIPE, stdout=sp.PIPE)			
			print run
			#os.execv(sys.argv[0], sys.argv)
		except Exception as e: log.info(e)
		else: sys.exit()
		
	def destroy(self,menu): 
		log.info('Kill intensionally')
		exit()	

if __name__ == "__main__":
	sys.exit(Conny())

